package com.sikaryofficial.workbench.manager;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.workbench.constant.MembershipPolicyEnum;
import com.sikaryofficial.workbench.domain.dto.req.membership.MembershipListReq;
import com.sikaryofficial.workbench.domain.dto.req.membership.MembershipPolicySaveReq;
import com.sikaryofficial.workbench.domain.dto.req.membership.MembershipRelationReq;
import com.sikaryofficial.workbench.domain.dto.req.membership.MembershipUpdateStatusReq;
import com.sikaryofficial.workbench.domain.dto.resp.membership.MembershipPolicyDTO;
import com.sikaryofficial.workbench.domain.dto.resp.membership.MembershipRelationDTO;
import com.sikaryofficial.workbench.domain.entity.MembershipPolicy;
import com.sikaryofficial.workbench.domain.entity.MembershipPolicyLog;
import com.sikaryofficial.workbench.domain.entity.MembershipRelation;
import com.sikaryofficial.workbench.domain.mapping.MembershipMapping;
import com.sikaryofficial.workbench.domain.mapping.MembershipRelationMapping;
import com.sikaryofficial.workbench.service.IMembershipPolicyLogService;
import com.sikaryofficial.workbench.service.IMembershipPolicyService;
import com.sikaryofficial.workbench.service.IMembershipRelationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : wuweihong
 * @desc : 会员激励政策服务
 * @date : 2024-10-20
 */

@Service
@Slf4j
public class MembershipPolicyManager {

    @Autowired
    private IMembershipPolicyService membershipPolicyService;

    @Autowired
    private IMembershipRelationService membershipRelationService;

    @Autowired
    private IMembershipPolicyLogService membershipPolicyLogService;

    /**
     * 分页获取会员激励政策列表
     * @param listReq 分页请求
     * @return 分页响应实体
     */
    public IPage<MembershipPolicyDTO> listMembershipPage(MembershipListReq listReq) {
        Page<MembershipPolicyDTO> customPage = new Page<>(listReq.getPageNum(), listReq.getPageSize());
        IPage<MembershipPolicyDTO> page = membershipPolicyService.membershipList(customPage, listReq);
        for (MembershipPolicyDTO membershipPolicyDTO : page.getRecords()) {
            membershipPolicyDTO.setStatusDesc(Objects.requireNonNull(MembershipPolicyEnum.getByCode(membershipPolicyDTO.getStatus())).getDesc());
        }
        List<Long> membershipIds = page.getRecords().stream().map(MembershipPolicyDTO::getMembershipPolicyId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(membershipIds)) {
            List<MembershipRelation> membershipRelations = membershipRelationService.lambdaQuery().eq(MembershipRelation::getDeletedVersion, 0).in(MembershipRelation::getMembershipPolicyId, membershipIds).list();
            List<MembershipRelationDTO> membershipRelationDTOS = MembershipRelationMapping.INSTANCE.coverToListResp(membershipRelations);
            Map<Long, List<MembershipRelationDTO>> membershipRelationMap = membershipRelationDTOS.stream().collect(Collectors.groupingBy(MembershipRelationDTO::getMembershipPolicyId));
            page.getRecords().forEach(item -> item.setUsers(membershipRelationMap.get(item.getMembershipPolicyId())));
        }
        return page;
    }

    /**
     * 验证参数：1. 同一个用户只能指定一个会员激励政策
     *         2. 未指定用户的会员激励政策只能有一个
     * @param saveReq 会员激励请求实体
     */
    private void validateParameters(MembershipPolicySaveReq saveReq) {
        List<MembershipRelationReq> currentUsers = Optional.ofNullable(saveReq.getUsers()).orElse(new ArrayList<>());
        List<Long> currentUserIds = currentUsers.stream().map(MembershipRelationReq::getUserId).collect(Collectors.toList());
        List<Long> memberUsers = getMembershipUsers(saveReq.getMembershipPolicyId());
        if (Objects.isNull(saveReq.getHasSpecificUser()) || Boolean.FALSE.equals(saveReq.getHasSpecificUser())) {
            MembershipPolicy membershipPolicyNotUser = membershipPolicyService.lambdaQuery()
                    .eq(MembershipPolicy::getDeletedVersion, 0)
                    .eq(MembershipPolicy::getHasSpecificUser, false)
                    .one();
            if (Objects.nonNull(membershipPolicyNotUser) && !membershipPolicyNotUser.getMembershipPolicyId().equals(saveReq.getMembershipPolicyId())) {
                throw new ServiceException("已经存在全局激励政策.");
            }
        }else {
            if (CollectionUtils.isNotEmpty(currentUserIds)) {
                boolean hasRepeatUser = memberUsers.stream().anyMatch(currentUserIds::contains);
                if (hasRepeatUser) {
                    throw new ServiceException("每个用户只能享受一个会员激励政策.");
                }
            } else {
                throw new ServiceException("指定用户不能为空.");
            }
        }
        if (Objects.nonNull(saveReq.getMaxAmount()) && saveReq.getMinAmount().compareTo(saveReq.getMaxAmount())>=0) {
            throw new ServiceException("最大值必须大于最小值.");
        }
    }

    /**
     * 保存激励政策
     * @param saveReq 会员激励请求实体
     * @return 会员激励id
     */
    @Transactional(rollbackFor = Exception.class)
    public Long saveMembershipPolicy(MembershipPolicySaveReq saveReq) {
        this.validateParameters(saveReq);
        MembershipPolicy membershipPolicy = MembershipMapping.INSTANCE.coverToSaveReq(saveReq);
        if (Objects.isNull(membershipPolicy.getMembershipPolicyId())) {
            membershipPolicy.setMembershipPolicyId(IdWorker.getId());
        }
        saveMembershipRelation(saveReq.getUsers(), membershipPolicy.getMembershipPolicyId());
        membershipPolicyService.saveOrUpdate(membershipPolicy);
        saveLog(membershipPolicy.getMembershipPolicyId());
        return membershipPolicy.getMembershipPolicyId();
    }

    /**
     * 保存用户会员关系: db中存在新传递过来的users中没有的用户，则需要删除
     * @param users 用户列表
     * @param membershipPolicyId 会员激励id
     */
    private void saveMembershipRelation(List<MembershipRelationReq> users, Long membershipPolicyId) {
        if (CollUtil.isEmpty(users)){
            membershipRelationService.lambdaUpdate()
                    .setSql(" deleted_version=membership_relation_id ")
                    .eq(MembershipRelation::getDeletedVersion, 0)
                    .eq(MembershipRelation::getMembershipPolicyId, membershipPolicyId)
                    .update();
            return;
        }

        LambdaUpdateWrapper<MembershipRelation> updateWrapper = new LambdaUpdateWrapper<MembershipRelation>()
                .setSql(" deleted_version=membership_relation_id ")
                .eq(MembershipRelation::getDeletedVersion, 0)
                .eq(MembershipRelation::getMembershipPolicyId, membershipPolicyId);
        users = users.stream().distinct().collect(Collectors.toList());
        List<Long> newMembershipRelationIds = users.stream()
                .map(MembershipRelationReq::getMembershipRelationId)
                .filter(Objects::nonNull).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(newMembershipRelationIds)) {
            updateWrapper.notIn(MembershipRelation::getMembershipRelationId, newMembershipRelationIds);
        }
        membershipRelationService.update(updateWrapper);
        List<MembershipRelation> membershipRelations = MembershipRelationMapping.INSTANCE.coverToListReq(users);
        membershipRelations.forEach(item -> item.setMembershipPolicyId(membershipPolicyId));
        membershipRelationService.saveOrUpdateBatch(membershipRelations);
    }

    /**
     * 批量更新激励政策状态
     * @param updateStatusReq 批量更新请求体
     * @return 返回是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatchStatus(MembershipUpdateStatusReq updateStatusReq) {
        if (CollUtil.isEmpty(updateStatusReq.getMembershipPolicyIds())) {
            return false;
        }
        MembershipPolicyEnum statusEnum = MembershipPolicyEnum.getByCode(updateStatusReq.getStatus());
        if (Objects.isNull(statusEnum)) {
            return false;
        }
        boolean operateResult = membershipPolicyService.update(new LambdaUpdateWrapper<MembershipPolicy>()
                .set(MembershipPolicy::getStatus, statusEnum.getCode())
                .set(MembershipPolicy::getUpdatedTime, new Date())
                .set(MembershipPolicy::getUpdatedBy, SecurityUtils.getUserId())
                .eq(MembershipPolicy::getDeletedVersion, 0)
                .in(MembershipPolicy::getMembershipPolicyId, updateStatusReq.getMembershipPolicyIds())
        );
        saveBatchLog(updateStatusReq.getMembershipPolicyIds());
        return operateResult;
    }

    /**
     * 批量删除激励政策
     * @param membershipPolicyIds
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBatch(List<Long> membershipPolicyIds) {
        if (CollUtil.isEmpty(membershipPolicyIds)) {
            return false;
        }
        try {
            boolean result = membershipPolicyService.lambdaUpdate()
                    .setSql("deleted_version = membership_policy_id")
                    .set(MembershipPolicy::getUpdatedBy, SecurityUtils.getUserId())
                    .set(MembershipPolicy::getUpdatedTime, new Date())
                    .in(MembershipPolicy::getMembershipPolicyId, membershipPolicyIds)
                    .update();
            membershipRelationService.lambdaUpdate()
                    .setSql("deleted_version = membership_relation_id")
                    .set(MembershipRelation::getUpdatedBy, SecurityUtils.getUserId())
                    .set(MembershipRelation::getUpdatedTime, new Date())
                    .in(MembershipRelation::getMembershipPolicyId, membershipPolicyIds)
                    .update();
            saveBatchLog(membershipPolicyIds);
            return result;
        }catch (Exception e) {
            log.error("删除会员激励政策失败:" + e.getMessage());
            throw new ServiceException("删除会员激励政策失败:" + e.getMessage());
        }
    }

    /**
     * 生成操作日志
     * @param membershipPolicyId
     * @return
     */
    private MembershipPolicyLog buildOperateLog(Long membershipPolicyId) {
        MembershipPolicyLog log = new MembershipPolicyLog();
        log.setMembershipPolicyId(membershipPolicyId);
        log.setMembershipPolicyLogId(IdWorker.getId());
        log.setModifyTime(new Date());
        log.setModifyUserId(SecurityUtils.getUserId());
        log.setModifyUserName(SecurityUtils.getUsername());
        return log;
    }

    /**
     * 保存操作日志
     * @param membershipPolicyId
     */
    private void saveLog(Long membershipPolicyId) {
        membershipPolicyLogService.save(buildOperateLog(membershipPolicyId));
    }

    /**
     * 批量保存操作日志
     *
     * @param ids
     */
    private void saveBatchLog(List<Long> ids) {
        membershipPolicyLogService.saveBatch(ids.stream().map(this::buildOperateLog).collect(Collectors.toList()));
    }

    /**
     * 查询操作日志
     * @param membershipPolicyId
     * @return
     */
    public List<MembershipPolicyLog> getLogList(Long membershipPolicyId) {
        if (Objects.isNull(membershipPolicyId)) {
            return Lists.newArrayList();
        }
        return membershipPolicyLogService.lambdaQuery()
                .eq(MembershipPolicyLog::getMembershipPolicyId, membershipPolicyId)
                .orderByDesc(MembershipPolicyLog::getModifyTime)
                .list();
    }


    /**
     * 获取详情
     * @param membershipPolicyId
     * @return
     */
    public MembershipPolicyDTO getDetail(Long membershipPolicyId) {
        MembershipPolicyDTO membershipPolicyDTO = MembershipMapping.INSTANCE.coverToResp(getById(membershipPolicyId));
        if (Boolean.TRUE.equals(membershipPolicyDTO.getHasSpecificUser())) {
            List<MembershipRelation> membershipRelations = membershipRelationService.lambdaQuery()
                    .eq(MembershipRelation::getDeletedVersion, 0)
                    .eq(MembershipRelation::getMembershipPolicyId, membershipPolicyId)
                    .list();
            List<MembershipRelationDTO> membershipRelationDTOS = MembershipRelationMapping.INSTANCE.coverToListResp(membershipRelations);
            membershipPolicyDTO.setUsers(membershipRelationDTOS);
        }
        return membershipPolicyDTO;
    }


    private MembershipPolicy getById(Long membershipPolicyId) {
        MembershipPolicy membershipPolicy = membershipPolicyService.getOne(new LambdaQueryWrapper<MembershipPolicy>()
                .eq(MembershipPolicy::getDeletedVersion, 0)
                .eq(MembershipPolicy::getMembershipPolicyId, membershipPolicyId)
        );
        if (Objects.isNull(membershipPolicy)) {
            throw new ServiceException("会员激励不存在.");
        }
        return membershipPolicy;
    }

    /**
     * 获取会员列表
     * @param membershipPolicyId
     * @return
     */
    public List<Long> getMembershipUsers(Long membershipPolicyId) {
        LambdaQueryWrapper<MembershipRelation> queryWrapper = new LambdaQueryWrapper<MembershipRelation>()
                .select(MembershipRelation::getUserId)
                .eq(MembershipRelation::getDeletedVersion, 0);
        if (Objects.nonNull(membershipPolicyId)) {
            queryWrapper.ne(MembershipRelation::getMembershipPolicyId, membershipPolicyId);
        }
        List<MembershipRelation> membershipUserList = membershipRelationService.list(queryWrapper);
        return membershipUserList.stream().map(MembershipRelation::getUserId).collect(Collectors.toList());
    }


}
